/*********************************************************************\
*         Jamper - Java XML mapper (visual XSLT generator)            *
*                Copyright (C) 2005 Filip Pavlovic                    *
*                    sqba@users.sourceforge.net                       *
*                                                                     *
*  This program is free software; you can redistribute it and/or      *
*  modify it under the terms of the GNU General Public License        *
*  as published by the Free Software Foundation; either version 2     *
*  of the License, or (at your option) any later version.             *
*                                                                     *
*  This program is distributed in the hope that it will be useful,    *
*  but WITHOUT ANY WARRANTY; without even the implied warranty of     *
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *
*  GNU General Public License for more details.                       *
*                                                                     *
*  You should have received a copy of the GNU General Public License  *
*  along with this program; if not, write to the Free Software        *
*  Foundation, Inc., 59 Temple Place - Suite 330, Boston,             *
*  MA 02111-1307, USA.                                                *
*                                                                     *
\*********************************************************************/


package sqba.jamper.map.tree.model;


import sqba.jamper.map.tree.MapperTree;
import sqba.jamper.map.tree.MapperTreeNode;
import sqba.jamper.util.PathList;

//import java.io.File;
import java.io.IOException;
//import java.io.FileInputStream;
//import java.io.FileNotFoundException;

//import javax.swing.JTree;
import javax.swing.tree.TreePath;
//import javax.swing.tree.DefaultTreeModel;
//import javax.swing.event.TreeModelListener;

import org.xml.sax.Locator;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.ContentHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.InputSource;
import org.xml.sax.helpers.ParserAdapter;


/**
 * Simple XML document loader class using the SAX API.
 * 
 * @author Filip Pavlovic
 * @version 1.0
 */
public class SAXTreeModel extends MapperTreeModel
{
	protected MapperTreeNode	_parent		= null;
	private MapperTree			_tree		= null;
	private boolean				_bStart		= true;
	private PathList			_path		= new PathList();
	private InputSource			_inputSource = null;
	protected String			_uri		= "";
	

    public SAXTreeModel(MapperTreeNode newRoot)
    {
		super(newRoot);
		_parent = newRoot;
		this._tree = newRoot.getTree();
    }

	private boolean load()
	{
		//System.out.println("Processing URL " + _urlString);
		SAXParserFactory spf = SAXParserFactory.newInstance();
		try {
			SAXParser sp = spf.newSAXParser();
			ParserAdapter pa = new ParserAdapter(sp.getParser());
			pa.setContentHandler(new MyContentHandler());
			pa.parse(_inputSource);
			//pa.parse(_urlString);
			// Ako se ne pozove setRoot onda root node ostaje prazan!
			// Ovo je vezano za MapperTreeNode.isLeaf. Da li je ovo bag?
			
			/*try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
			    e.printStackTrace();
			}*/
			
			setRoot((MapperTreeNode)getRoot());
			((MapperTree)SAXTreeModel.this._tree).expandAll(new TreePath(root), true);
			super._bLoaded = true;
			return true;
		} catch (ParserConfigurationException e) {
			System.out.println("Processing URL error: " + e);
		} catch (SAXException e) {
			System.out.println("Processing URL error: " + e);
		} catch (IOException e) {
			System.out.println("Processing URL error: " + e);
		}
		return false;
	}
	
	public boolean Load(InputSource inputSource)
	{
		super._bLoaded = false;
		_bStart = true;
		_inputSource = inputSource;
		//_myThread = new Thread(this);
		//_myThread.start();
		return load();
	}

	public boolean Load(String uri)
	{
		super._bLoaded = false;
		_bStart = true;
		this._uri = uri;
		_inputSource = new InputSource(uri);
		return load();
	}
	
	class MyContentHandler implements ContentHandler
	{
		public void characters(char[] ch, int start, int length)
		{
			if(_parent != null)
				_parent.setValue(new String(ch, start, length));
		}
		public void endDocument() {}
		public void endPrefixMapping(String prefix) {}
		public void ignorableWhitespace(char[] ch, int start, int length) {}
		public void processingInstruction(String target, String data) {}
		public void setDocumentLocator(Locator locator) {}
		public void skippedEntity(String name) {}
		public void startDocument() {}
		public void startPrefixMapping(String prefix, String uri) {}
		
		public void startElement(String uri, String localName, 
								 String qName, Attributes attrs)
		{
			_path.add(qName);

			MapperTreeNode newNode = new MapperTreeNode(qName, SAXTreeModel.this._tree);
			newNode.setAllowsChildren(true);
			
			if (_bStart) {
				setRoot(newNode);
				_bStart = false;
			} else
				_parent.add(newNode);

			_parent = newNode;
			
			if (attrs != null) {
				MapperTreeNode attNode;
			    for (int i = 0; i < attrs.getLength(); i++) {
			    	String attName = attrs.getLocalName(i);
			    	String val = attrs.getValue(i);
					attNode = new MapperTreeNode(attName, SAXTreeModel.this._tree, true);
					if(val.length() > 0)
						attNode.setValue(val);
					attNode.setAllowsChildren(false);
					newNode.add(attNode);
			    }
			}

			//System.out.println(">" + _path + " " + _parent);
		}
		
		public void endElement(String uri, String localName, String qName)
		{
			_parent = (MapperTreeNode)_parent.getParent();
			
			if(!qName.equals(_path.getLast()))
				System.out.println("Malformed XML document!");

			_path.removeLast();
			
			//System.out.println("<" + _path + " " + _parent);
		}
	}

    public void valueForPathChanged(TreePath path, Object newValue)
    {
		MapperTreeNode node = (MapperTreeNode)path.getLastPathComponent();
		node.setName((String)newValue);
		nodeChanged(node);
    }
}
